1 using System.Collections.Generic;
2 using
UnityEngine;
3 using
System.Collections;
4 using
Hashtable = ExitGames.Client.Photon.Hashtable;
5
6
7 ///
<summary>
8 ///
Makes a scene object pickup-able. Needs a PhotonView which belongs to the scene.
9 ///
</summary>
10 ///
<remarks>Includes a OnPhotonSerializeView implementation that </remarks>
11 [RequireComponent(
typeof(PhotonView))]
12 public
class PickupItem : Photon.MonoBehaviour, IPunObservable
13 {

14     ///<summary>
Enables you to define a timeout when the picked up item should re-spawn at the same place it was before.</summary>
15     ///
<remarks>
16     ///
Set in Inspector per GameObject! The value in code is just the default.
17     ///

18     ///
If you don't want an item to respawn, set SecondsBeforeRespawn == 0.
19     ///
If an item does not respawn, it could be consumed or carried around and dropped somewhere else.
20     ///

21     ///
A respawning item should stick to a fixed position. It should not be observed at all (in any PhotonView).
22     ///
It can only be consumed and can't be dropped somewhere else (cause that would double the item).
23     ///

24     ///
This script uses PunRespawn() as RPC and as method that gets called by Invoke() after a timeout.
25     ///
No matter if the item respawns timed or by Drop, that method makes sure (temporary) owner and other status-values
26     ///
are being re-set.
27     ///
</remarks>
28     
public float SecondsBeforeRespawn = 2;
29     
30     ///
<summary>The most likely trigger to pick up an item. Set in inspector!</summary>
31     ///
<remarks>Edit the collider and set collision masks to avoid pickups by random objects.</remarks>
32     
public bool PickupOnTrigger;
33
34     ///
<summary>If the pickup item is currently yours. Interesting in OnPickedUp(PickupItem item).</summary>
35     
public bool PickupIsMine;
36
37     ///
<summary>GameObject to send an event "OnPickedUp(PickupItem item)" to.</summary>
38     ///
<remarks>
39     ///
Implement OnPickedUp(PickupItem item) {} in some script on the linked game object.
40     ///
The item will be "this" and item.PickupIsMine will help you to find if this pickup was done by "this player".
41     ///
</remarks>
42     
public MonoBehaviour OnPickedUpCall;
43
44
45     
// these values are internally used. they are public for debugging only
46     
47     ///
<summary>If this client sent a pickup. To avoid sending multiple pickup requests before reply is there.</summary>
48     
public bool SentPickup;
49     
50     ///
<summary>Timestamp when to respawn the item (compared to PhotonNetwork.time). </summary>
51     
public double TimeOfRespawn; // needed when we want to update new players when a PickupItem respawns
52     
53     ///
<summary></summary>
54     
public int ViewID { get { return this.photonView.viewID; } }
55
56     
public static HashSet<PickupItem> DisabledPickupItems = new HashSet<PickupItem>();
57
58
59     
public void OnTriggerEnter(Collider other)
60     {
61         
// we only call Pickup() if "our" character collides with this PickupItem.
62         
// note: if you "position" remote characters by setting their translation, triggers won't be hit.
63
64         PhotonView otherpv = other.GetComponent<PhotonView>();
65         
if (this.PickupOnTrigger && otherpv != null && otherpv.isMine)
66         {
67             
//Debug.Log("OnTriggerEnter() calls Pickup().");
68             
this.Pickup();
69         }
70     }
71
72
73
74     
public void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info)
75     {
76         
// read the description in SecondsBeforeRespawn
77
78         
if (stream.isWriting && SecondsBeforeRespawn <= 0)
79         {
80             stream.SendNext(
this.gameObject.transform.position);
81         }
82         
else
83         {
84             
// this will directly apply the last received position for this PickupItem. No smoothing. Usually not needed though.
85             Vector3 lastIncomingPos = (Vector3)stream.ReceiveNext();
86             
this.gameObject.transform.position = lastIncomingPos;
87         }
88     }
89
90
91     
public void Pickup()
92     {
93         
if (this.SentPickup)
94         {
95             
// skip sending more pickups until the original pickup-RPC got back to this client
96             
return;
97         }
98         
99         
this.SentPickup = true;
100         
this.photonView.RPC("PunPickup", PhotonTargets.AllViaServer);
101     }

102
103     
104     ///
<summary>Makes use of RPC PunRespawn to drop an item (sent through server for all).</summary>
105     
public void Drop()
106     {
107         
if (this.PickupIsMine)
108         {
109             
this.photonView.RPC("PunRespawn", PhotonTargets.AllViaServer);
110         }
111     }

112
113     ///
<summary>Makes use of RPC PunRespawn to drop an item (sent through server for all).</summary>
114     
public void Drop(Vector3 newPosition)
115     {
116         
if (this.PickupIsMine)
117         {
118             
this.photonView.RPC("PunRespawn", PhotonTargets.AllViaServer, newPosition);
119         }
120     }
121
122
123     
[RPC]
124     
public void PunPickup(PhotonMessageInfo msgInfo)
125     {
126         
// when this client's RPC gets executed, this client no longer waits for a sent pickup and can try again
127         
if (msgInfo.sender.isLocal) this.SentPickup = false;
128
129
130         
// In this solution, picked up items are disabled. They can't be picked up again this way, etc.
131         
// You could check "active" first, if you're not interested in failed pickup-attempts.
132         
if (!this.gameObject.GetActive())
133         {
134             
// optional logging:
135             Debug.Log(
"Ignored PU RPC, cause item is inactive. " + this.gameObject + " SecondsBeforeRespawn: " + SecondsBeforeRespawn + " TimeOfRespawn: " + this.TimeOfRespawn + " respawn in future: " + (TimeOfRespawn > PhotonNetwork.time));
136             
return; // makes this RPC being ignored
137         }
138
139         
140         
// if the RPC isn't ignored by now, this is a successful pickup. this might be "my" pickup and we should do a callback
141         
this.PickupIsMine = msgInfo.sender.isLocal;
142         
143         
// call the method OnPickedUp(PickupItem item) if a GameObject was defined as callback target
144         
if (this.OnPickedUpCall != null)
145         {
146             
// you could also skip callbacks for items that are not picked up by this client by using: if (this.PickupIsMine)
147             
this.OnPickedUpCall.SendMessage("OnPickedUp", this);
148         }
149
150
151         
// setup a respawn (or none, if the item has to be dropped)
152         
if (SecondsBeforeRespawn <= 0)
153         {
154             
this.PickedUp(0.0f); // item doesn't auto-respawn. must be dropped
155         }
156         
else
157         {
158             
// how long it is until this item respanws, depends on the pickup time and the respawn time
159             
double timeSinceRpcCall = (PhotonNetwork.time - msgInfo.timestamp);
160             
double timeUntilRespawn = SecondsBeforeRespawn - timeSinceRpcCall;
161
162             
//Debug.Log("msg timestamp: " + msgInfo.timestamp + " time until respawn: " + timeUntilRespawn);
163
164             
if (timeUntilRespawn > 0)
165             {
166                 
this.PickedUp((float)timeUntilRespawn);
167             }
168         }
169     }
170
171     
internal void PickedUp(float timeUntilRespawn)
172     {
173         
// this script simply disables the GO for a while until it respawns.
174         
this.gameObject.SetActive(false);
175         PickupItem.DisabledPickupItems.Add(
this);
176         
this.TimeOfRespawn = 0;
177
178         
if (timeUntilRespawn > 0)
179         {
180             
this.TimeOfRespawn = PhotonNetwork.time + timeUntilRespawn;
181             Invoke(
"PunRespawn", timeUntilRespawn);
182         }
183     }
184
185
186     
[RPC]
187     
internal void PunRespawn(Vector3 pos)
188     {
189         Debug.Log(
"PunRespawn with Position.");
190         
this.PunRespawn();
191         
this.gameObject.transform.position = pos;
192     }
193
194     
[RPC]
195     
internal void PunRespawn()
196     {
197         #
if DEBUG
198         
// debugging: in some cases, the respawn is "late". it's unclear why! just be aware of this.
199         
double timeDiffToRespawnTime = PhotonNetwork.time - this.TimeOfRespawn;
200         
if (timeDiffToRespawnTime > 0.1f) Debug.LogWarning("Spawn time is wrong by: " + timeDiffToRespawnTime + " (this is not an error. you just need to be aware of this.)");
201         #endif
202
203
204         
// if this is called from another thread, we might want to do this in OnEnable() instead of here (depends on Invoke's implementation)
205         PickupItem.DisabledPickupItems.Remove(
this);
206         
this.TimeOfRespawn = 0;
207         
this.PickupIsMine = false;
208
209         
if (this.gameObject != null)
210         {
211             
this.gameObject.SetActive(true);
212         }
213     }
214 }


Makes a scene object pickup-able. Needs a PhotonView which belongs to the scene.

Includes a OnPhotonSerializeView implementation that

Enables you to define a timeout when the picked up item should re-spawn at the same place it was before.

Set in Inspector per GameObject! The value in code is just the default.

If you don't want an item to respawn, set SecondsBeforeRespawn == 0.

If an item does not respawn, it could be consumed or carried around and dropped somewhere else.

A respawning item should stick to a fixed position. It should not be observed at all (in any PhotonView).

It can only be consumed and can't be dropped somewhere else (cause that would double the item).

This script uses PunRespawn() as RPC and as method that gets called by Invoke() after a timeout.

No matter if the item respawns timed or by Drop, that method makes sure (temporary) owner and other status-values

are being re-set.

The most likely trigger to pick up an item. Set in inspector!

Edit the collider and set collision masks to avoid pickups by random objects.

If the pickup item is currently yours. Interesting in OnPickedUp(PickupItem item).

GameObject to send an event "OnPickedUp(PickupItem item)" to.

Implement OnPickedUp(PickupItem item) {} in some script on the linked game object.

The item will be "this" and item.PickupIsMine will help you to find if this pickup was done by "this player".

these values are internally used. they are public for debugging only

If this client sent a pickup. To avoid sending multiple pickup requests before reply is there.

Timestamp when to respawn the item (compared to PhotonNetwork.time).

public double TimeOfRespawn; needed when we want to update new players when a PickupItem respawns

we only call Pickup() if "our" character collides with this PickupItem.

note: if you "position" remote characters by setting their translation, triggers won't be hit.

Debug.Log("OnTriggerEnter() calls Pickup().");

read the description in SecondsBeforeRespawn

this will directly apply the last received position for this PickupItem. No smoothing. Usually not needed though.

skip sending more pickups until the original pickup-RPC got back to this client

Makes use of RPC PunRespawn to drop an item (sent through server for all).

Makes use of RPC PunRespawn to drop an item (sent through server for all).

when this client's RPC gets executed, this client no longer waits for a sent pickup and can try again

In this solution, picked up items are disabled. They can't be picked up again this way, etc.

You could check "active" first, if you're not interested in failed pickup-attempts.

optional logging:

return; makes this RPC being ignored

if the RPC isn't ignored by now, this is a successful pickup. this might be "my" pickup and we should do a callback

call the method OnPickedUp(PickupItem item) if a GameObject was defined as callback target

you could also skip callbacks for items that are not picked up by this client by using: if (this.PickupIsMine)

setup a respawn (or none, if the item has to be dropped)

this.PickedUp(0.0f); item doesn't auto-respawn. must be dropped

how long it is until this item respanws, depends on the pickup time and the respawn time

Debug.Log("msg timestamp: " + msgInfo.timestamp + " time until respawn: " + timeUntilRespawn);

this script simply disables the GO for a while until it respawns.

debugging: in some cases, the respawn is "late". it's unclear why! just be aware of this.

if this is called from another thread, we might want to do this in OnEnable() instead of here (depends on Invoke's implementation)




Trò chơi Tic-Tac-Toe, game đánh caro full source code 53.446 lượt xem

Gõ tìm kiếm nhanh...